home *** CD-ROM | disk | FTP | other *** search
/ GFX Sensations 1 / Graphic Sensations - Volume 1.iso / tools / amiga / 3d_tools / irit40s.lha / Irit / cagd_lib / cagdcmrg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-30  |  10.7 KB  |  346 lines

  1. /******************************************************************************
  2. * CagdCMrg.c - Curve/Point merging routines.                      *
  3. *******************************************************************************
  4. * Written by Gershon Elber, May 91.                          *
  5. ******************************************************************************/
  6.  
  7. #include "string.h"
  8. #include "cagd_loc.h"
  9.  
  10. static void CopyCrvOnCrv(CagdCrvStruct *DestCrv, int Index,
  11.              CagdCrvStruct *SrcCrv);
  12. static void InterpolateLinearSeg(CagdCrvStruct *Crv, int Index1, int Index2);
  13.  
  14. /******************************************************************************
  15. * Merge two curves.                                  *
  16. ******************************************************************************/
  17. CagdCrvStruct *CagdMergeCrvCrv(CagdCrvStruct *Crv1, CagdCrvStruct *Crv2)
  18. {
  19.     CagdBType CrvsSharePt;
  20.     int Length, Order, Len1, Len2;
  21.     CagdRType E3Pt1[3], E3Pt2[3];
  22.     CagdPointType CrvPType;
  23.     CagdCrvStruct *Crv;
  24.  
  25.     Crv1 = CagdCrvCopy(Crv1);
  26.     Crv2 = CagdCrvCopy(Crv2);
  27.     CagdMakeCrvsCompatible(&Crv1, &Crv2, TRUE, FALSE);
  28.     Order = Crv1 -> Order;
  29.     Len1 = Crv1 -> Length;
  30.     Len2 = Crv2 -> Length;
  31.  
  32.     /* Verify curve geometric types. */
  33.     switch (Crv1 -> GType) {
  34.     case CAGD_CBEZIER_TYPE:
  35.         Crv = CnvrtBezier2BsplineCrv(Crv1);
  36.         CagdCrvFree(Crv1);
  37.         Crv1 = Crv;
  38.         break;
  39.     case CAGD_CBSPLINE_TYPE:
  40.         break;
  41.     case CAGD_CPOWER_TYPE:
  42.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  43.         break;
  44.     default:
  45.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  46.         break;
  47.     }
  48.  
  49.     switch (Crv2 -> GType) {
  50.     case CAGD_CBEZIER_TYPE:
  51.         Crv = CnvrtBezier2BsplineCrv(Crv2);
  52.         CagdCrvFree(Crv2);
  53.         Crv2 = Crv;
  54.         break;
  55.     case CAGD_CBSPLINE_TYPE:
  56.         break;
  57.     case CAGD_CPOWER_TYPE:
  58.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  59.         break;
  60.     default:
  61.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  62.         break;
  63.     }
  64.  
  65.     /* Compute curve point types. */
  66.     CrvPType = Crv1 -> PType;
  67.  
  68.     /* Figure out if end point of Crv1 is equal to start point of Crv2 and   */
  69.     /* Compute the length of the resulting curve accordingly.             */
  70.     /* If the same point, then the result can omit one copy and therefore    */
  71.     /* has Len1 + Len2 - 1 Ctl points. If however a linear segment should be */
  72.     /* introduced between the two curves, it should hold Order colinear pts  */
  73.     /* including 2 end points shared with curves or Order - 2 new pts.       */
  74.     CagdCoerceToE3(E3Pt1, Crv1 -> Points, Len1 - 1, Crv1 -> PType);
  75.     CagdCoerceToE3(E3Pt2, Crv2 -> Points, 0, Crv2 -> PType);
  76.     CrvsSharePt = PT_APX_EQ(E3Pt1, E3Pt2);
  77.     Length = CrvsSharePt ? Len1 + Len2 - 1 : Len1 + Len2 + Order - 2;
  78.  
  79.     Crv = BspCrvNew(Length, Order, CrvPType);
  80.     CopyCrvOnCrv(Crv, 0, Crv1);
  81.     CopyCrvOnCrv(Crv, Length - Len2, Crv2);
  82.     InterpolateLinearSeg(Crv, Len1 - 1, Length - Len2);
  83.  
  84.     /* Update the knot vector. We assume open end condition here... */
  85.     CAGD_GEN_COPY(Crv -> KnotVector, Crv1 -> KnotVector,
  86.           (Len1 + Order - 1) * sizeof(CagdRType));
  87.     if (CrvsSharePt) {
  88.     CAGD_GEN_COPY(&Crv -> KnotVector[Len1 + Order - 1],
  89.               &Crv2 -> KnotVector[Order], Len2 * sizeof(CagdRType));
  90.     BspKnotAffineTrans(&Crv -> KnotVector[Len1 + Order - 1],
  91.                Len2,
  92.                Crv -> KnotVector[Len1 + Order - 2] -
  93.                Crv2 -> KnotVector[0],
  94.                1.0);
  95.     }
  96.     else {
  97.     CAGD_GEN_COPY(&Crv -> KnotVector[Len1 + Order - 1],
  98.               &Crv2 -> KnotVector[1],
  99.               (Len2 + Order - 1) * sizeof(CagdRType));
  100.     BspKnotAffineTrans(&Crv -> KnotVector[Len1 + Order - 1],
  101.                Len2 + Order - 1,
  102.                Crv -> KnotVector[Len1 + Order - 2] -
  103.                Crv -> KnotVector[Len1 + Order - 1] + 1.0,
  104.                1.0);
  105.     }
  106.  
  107.     CagdCrvFree(Crv1);
  108.     CagdCrvFree(Crv2);
  109.  
  110.     return Crv;
  111. }
  112.  
  113. /******************************************************************************
  114. * Merge a list of curves, in order.                          *
  115. ******************************************************************************/
  116. CagdCrvStruct *CagdMergeCrvList(CagdCrvStruct *CrvList)
  117. {
  118.     if (CrvList != NULL && CrvList -> Pnext != NULL) {
  119.     CagdCrvStruct
  120.         *MergedCrv = CrvList;
  121.  
  122.     for (CrvList = CrvList -> Pnext;
  123.          CrvList != NULL;
  124.          CrvList = CrvList -> Pnext) {
  125.         CagdCrvStruct
  126.         *TmpCrv = CagdMergeCrvCrv(MergedCrv, CrvList);
  127.  
  128.         CagdCrvFree(MergedCrv);
  129.         MergedCrv = TmpCrv;
  130.     }
  131.     return MergedCrv;
  132.     }
  133.     else
  134.     return CrvList ? CagdCrvCopy(CrvList) : NULL;
  135. }
  136.  
  137. /******************************************************************************
  138. * Merge a curve and a point.                              *
  139. ******************************************************************************/
  140. CagdCrvStruct *CagdMergeCrvPt(CagdCrvStruct *Crv, CagdPtStruct *Pt)
  141. {
  142.     CagdBType
  143.     CrvNew = FALSE,
  144.     IsRational = CAGD_IS_RATIONAL_CRV(Crv);
  145.     int i, NewLen, NewMaxCoord,
  146.     Order = Crv -> Order,
  147.     Len = Crv -> Length,
  148.     PtMaxCoord = APX_EQ(Pt -> Pt[2], 0.0) ? 2 : 3,
  149.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
  150.     CagdPointType
  151.     CrvPType = CAGD_PT_E2_TYPE;
  152.     CagdRType t, **Points;
  153.     CagdCrvStruct *NewCrv;
  154.  
  155.     switch (Crv -> GType) {
  156.     case CAGD_CBEZIER_TYPE:
  157.         Crv = CnvrtBezier2BsplineCrv(Crv);
  158.         CrvNew = TRUE;
  159.     case CAGD_CBSPLINE_TYPE:
  160.         break;
  161.     case CAGD_CPOWER_TYPE:
  162.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  163.         break;
  164.     default:
  165.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  166.         break;
  167.     }
  168.  
  169.     /* Compute curve point types. */
  170.     NewMaxCoord = MAX(PtMaxCoord, MaxCoord);
  171.     CrvPType = CAGD_MAKE_PT_TYPE(IsRational, NewMaxCoord);
  172.  
  173.     /* A linear segment is added at the end with Order colinear pts.        */
  174.     /* However since first point is curve last point, only Order - 1 new.   */
  175.     NewLen = Len + Order - 1;
  176.  
  177.     NewCrv = BspCrvNew(NewLen, Order, CrvPType);
  178.     Points = NewCrv -> Points;
  179.  
  180.     CopyCrvOnCrv(NewCrv, 0, Crv);
  181.     for (i = 1; i <= NewMaxCoord; i++)
  182.     Points[i][NewLen - 1] = Pt -> Pt[i - 1];
  183.     if (IsRational)
  184.     Points[W][NewLen - 1] = 1.0;
  185.     InterpolateLinearSeg(NewCrv, Len - 1, NewLen - 1);
  186.  
  187.     /* Update the knot vector. We assume open end condition here... */
  188.     CAGD_GEN_COPY(NewCrv -> KnotVector, Crv -> KnotVector,
  189.           (Len + Order - 1) * sizeof(CagdRType));
  190.     t = Crv -> KnotVector[Len + Order - 1] + 1.0;
  191.     for (i = Len + Order - 1; i < NewLen + Order; i++)
  192.     NewCrv -> KnotVector[i] = t;
  193.  
  194.     if (CrvNew)
  195.     CagdCrvFree(Crv);
  196.  
  197.     return NewCrv;
  198. }
  199.  
  200. /******************************************************************************
  201. * Merge a point and a curve.                              *
  202. ******************************************************************************/
  203. CagdCrvStruct *CagdMergePtCrv(CagdPtStruct *Pt, CagdCrvStruct *Crv)
  204. {
  205.     CagdBType
  206.     CrvNew = FALSE,
  207.     IsRational = CAGD_IS_RATIONAL_CRV(Crv);
  208.     int i, NewLen, NewMaxCoord,
  209.     Order = Crv -> Order,
  210.     Len = Crv -> Length,
  211.     PtMaxCoord = APX_EQ(Pt -> Pt[2], 0.0) ? 2 : 3,
  212.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
  213.     CagdPointType
  214.     CrvPType = CAGD_PT_E2_TYPE;
  215.     CagdRType t, **Points;
  216.     CagdCrvStruct *NewCrv;
  217.  
  218.     switch (Crv -> GType) {
  219.     case CAGD_CBEZIER_TYPE:
  220.         Crv = CnvrtBezier2BsplineCrv(Crv);
  221.         CrvNew = TRUE;
  222.         break;
  223.     case CAGD_CBSPLINE_TYPE:
  224.         break;
  225.     case CAGD_CPOWER_TYPE:
  226.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  227.         break;
  228.     default:
  229.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  230.         break;
  231.     }
  232.  
  233.     /* Compute curve point types. */
  234.     NewMaxCoord = MAX(PtMaxCoord, MaxCoord);
  235.     CrvPType = CAGD_MAKE_PT_TYPE(IsRational, NewMaxCoord);
  236.  
  237.     /* A linear segment is added at the end with Order colinear pts.        */
  238.     /* However since first point is curve last point, only Order - 1 new.   */
  239.     NewLen = Len + Order - 1;
  240.  
  241.     NewCrv = BspCrvNew(NewLen, Order, CrvPType);
  242.     Points = NewCrv -> Points;
  243.  
  244.     CopyCrvOnCrv(NewCrv, Order - 1, Crv);
  245.     for (i = 1; i <= NewMaxCoord; i++)
  246.     Points[i][0] = Pt -> Pt[i - 1];
  247.     if (IsRational)
  248.     Points[W][0] = 1.0;
  249.     InterpolateLinearSeg(NewCrv, 0, Order - 1);
  250.  
  251.     /* Update the knot vector. We assume open end condition here... */
  252.     CAGD_GEN_COPY(&NewCrv -> KnotVector[Order], &Crv -> KnotVector[1],
  253.           (Len + Order - 1) * sizeof(CagdRType));
  254.     t = Crv -> KnotVector[0] - 1.0;
  255.     for (i = 0; i < Order; i++)
  256.     NewCrv -> KnotVector[i] = t;
  257.  
  258.     if (CrvNew)
  259.     CagdCrvFree(Crv);
  260.  
  261.     return NewCrv;
  262. }
  263.  
  264. /******************************************************************************
  265. * Merge two points into a linear Bezier curve.                      *
  266. ******************************************************************************/
  267. CagdCrvStruct *CagdMergePtPt(CagdPtStruct *Pt1, CagdPtStruct *Pt2)
  268. {
  269.     CagdPointType
  270.     CrvPType = APX_EQ(Pt1 -> Pt[2], 0.0) && APX_EQ(Pt2 -> Pt[2], 0.0) ?
  271.                     CAGD_PT_E2_TYPE : CAGD_PT_E3_TYPE;
  272.     CagdCrvStruct
  273.     *Crv = BzrCrvNew(2, CrvPType);
  274.     CagdRType
  275.     **Points = Crv -> Points;
  276.  
  277.     Points[X][0] = Pt1 -> Pt[0];
  278.     Points[X][1] = Pt2 -> Pt[0];
  279.     Points[Y][0] = Pt1 -> Pt[1];
  280.     Points[Y][1] = Pt2 -> Pt[1];
  281.     if (CrvPType == CAGD_PT_E3_TYPE) {
  282.         Points[Z][0] = Pt1 -> Pt[2];
  283.         Points[Z][1] = Pt2 -> Pt[2];
  284.     }
  285.  
  286.     return Crv;
  287. }
  288.  
  289. /******************************************************************************
  290. * Copy SrcCrv into DestCrv at point index Index.                  *
  291. * DestCrv PType is assumed to hold Src PType.                      *
  292. ******************************************************************************/
  293. static void CopyCrvOnCrv(CagdCrvStruct *DestCrv, int Index,
  294.              CagdCrvStruct *SrcCrv)
  295. {
  296.     CagdBType
  297.     IsNotRational = !CAGD_IS_RATIONAL_CRV(SrcCrv);
  298.     int i, j,
  299.     Len = SrcCrv -> Length,
  300.     MaxCoord = CAGD_NUM_OF_PT_COORD(SrcCrv -> PType);
  301.     CagdRType
  302.     **SrcPoints = SrcCrv -> Points,
  303.     **DestPoints = DestCrv -> Points;
  304.  
  305.     for (i = IsNotRational; i <= MaxCoord; i++)
  306.     CAGD_GEN_COPY(&DestPoints[i][Index], SrcPoints[i],
  307.               Len * sizeof(CagdRType));
  308.  
  309.     /* Fix the weights if source did not have them. */
  310.     if (IsNotRational && CAGD_IS_RATIONAL_CRV(DestCrv))
  311.     for (i = Index; i < Index + Len; i++)
  312.         DestPoints[W][i] = 1.0;
  313.  
  314.     /* Fix the higher coordinates (by coercing them to zero. */
  315.     for (i = MaxCoord + 1; i < CAGD_NUM_OF_PT_COORD(DestCrv -> PType); i++)
  316.     for (j = Index; j < Index + Len; j++)
  317.         DestPoints[i][j] = 0.0;
  318.  
  319. }
  320.  
  321. /******************************************************************************
  322. * Linearly interpolate between the Crv points indices Index1 and Index2       *
  323. ******************************************************************************/
  324. static void InterpolateLinearSeg(CagdCrvStruct *Crv, int Index1, int Index2)
  325. {
  326.     CagdBType
  327.     IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
  328.     int i, j,
  329.     DIndex = Index2 - Index1,
  330.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
  331.     CagdRType
  332.     **Points = Crv -> Points;
  333.  
  334.     if (DIndex < 2)
  335.     return;                     /* No middle points to interp. */
  336.  
  337.     for (i = Index1 + 1; i < Index2; i++) {
  338.     CagdRType
  339.         t1 = ((CagdRType) (i - Index1)) / DIndex,
  340.         t2 = 1.0 - t1;
  341.  
  342.     for (j = IsNotRational; j <= MaxCoord; j++)
  343.         Points[j][i] = t2 * Points[j][Index1] + t1 * Points[j][Index2];
  344.     }
  345. }
  346.